﻿using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.Configuration;
using System.Net;
using System.Text.Json;
using System.Web;
using System.Security.Cryptography;
using System.Text;
using Microsoft.Extensions.DependencyInjection;
using Shop.Core.Consts;

namespace Shop.Core.Share
{
    public class SignatureAttribute : ActionFilterAttribute
    {
        public async override Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
        {
            var request = context.HttpContext.Request;
            var headers = request.Headers;

            string timestamp = string.Empty, nonce = string.Empty, signature = string.Empty;
            if (headers.ContainsKey("timestamp"))
                timestamp = HttpUtility.UrlDecode(headers["timestamp"][0]);
            if (headers.ContainsKey("nonce"))
                nonce = HttpUtility.UrlDecode(headers["nonce"][0]);
            if (headers.ContainsKey("signature"))
                signature = HttpUtility.UrlDecode(headers["signature"][0]);


            if (string.IsNullOrEmpty(timestamp) || string.IsNullOrEmpty(nonce) || string.IsNullOrEmpty(signature))
            {
                DateTimeOffset dto = new(DateTime.UtcNow);
                var lt = dto.ToUnixTimeMilliseconds();
                bool timespanvalidate = long.TryParse(timestamp, out long ts);
                if (timespanvalidate && lt - ts < 60000)
                {
                    if (request.ContentType == null || request.ContentType.Contains("application/json"))
                    {
                        request.EnableBuffering();
                        using var reader = new StreamReader(request.Body, Encoding.UTF8);
                        request.Body.Seek(0, SeekOrigin.Begin);
                        var data = await reader.ReadToEndAsync();
                        request.Body.Position = 0;

                        var signStr = $"timestamp={timestamp}&nonce={nonce}&data={data}&key={ShopConst.APIKey}";
                        using var md5 = MD5.Create();
                        var result = BitConverter.ToString(md5.ComputeHash(Encoding.UTF8.GetBytes(signStr)));
                        result = result.Replace("-", "");
                        if (string.Equals(signature, result))
                        {
                            await next();
                            return;
                        }
                    }
                }
            }

            context.Result = new ContentResult()
            {
                Content = JsonSerializer.Serialize(new
                {
                    code = HttpStatusCode.Unauthorized,
                    msg = "非法访问 - E001"
                }),
                ContentType = "application/json",
                StatusCode = 200
            };
            return;
        }
    }
}
